package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"sync"

	"github.com/gorilla/websocket"
	_ "github.com/joho/godotenv/autoload" // 自动加载 .env 文件
)

var (
	ENV                   = os.Getenv("ENV")
	CADDY_ERROR_LOG_PATH  = os.Getenv("CADDY_ERROR_LOG_PATH")
	DOCKER_CADDY_ERROR_LOG_PATH  = os.Getenv("DOCKER_CADDY_ERROR_LOG_PATH")
	CADDY_ACCESS_LOG_PATH = os.Getenv("CADDY_ACCESS_LOG_PATH")
	DOCKER_CADDY_ACCESS_LOG_PATH = os.Getenv("DOCKER_CADDY_ACCESS_LOG_PATH")
	CADDYFILE_PATH        = os.Getenv("CADDYFILE_PATH")
	caddyfilePath         = os.Getenv("CADDYFILE_PATH")
	serverPort            = os.Getenv("SERVER_PORT")
	frontPath             = os.Getenv("FRONT_PATH")
	CADDY_CMD_VERSION     = os.Getenv("CADDY_VERSION")
	CADDY_VALIDATE        = os.Getenv("CADDY_VALIDATE")
	CADDY_STOP            = os.Getenv("CADDY_STOP")
	CADDY_RESTART         = os.Getenv("CADDY_RESTART")
	CADDY_START           = os.Getenv("CADDY_START")

	upgrader              = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true // 开发环境允许所有来源
		},
	}
	caddyCmd   *exec.Cmd
	caddyMutex sync.Mutex
)

func loadEnv() {
	ENV = os.Getenv("ENV")
	fmt.Printf("当前环境：	%s\n", ENV)
	if ENV == "docker" {
		caddyfilePath = os.Getenv("DOCKER_CADDYFILE_PATH")
		frontPath = os.Getenv("DOCKER_FRONT_PATH")
		CADDY_ERROR_LOG_PATH = os.Getenv("DOCKER_CADDY_ERROR_LOG_PATH")
		CADDY_ACCESS_LOG_PATH = os.Getenv("DOCKER_CADDY_ACCESS_LOG_PATH")
	}
}

type Response struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

func main() {
	loadEnv()
	fmt.Printf("caddy 可执行文件路径：%s\n",os.Getenv("CADDY_BIN_PATH"))
	fmt.Printf("预览caddy 配置文件路径: %s\n", caddyfilePath)
	fmt.Printf("前端静态文件地址: %s\n", frontPath)
	fmt.Printf("caddy 访问日志路径: %s\n", CADDY_ACCESS_LOG_PATH)
	fmt.Printf("caddy 错误日志路径: %s\n", CADDY_ERROR_LOG_PATH)
	fmt.Printf("在宿主机运行caddy命令的配置文件路径: %s\n", CADDYFILE_PATH)
	fmt.Printf("运行查看caddy版本命令: %s\n", CADDY_CMD_VERSION)
	fmt.Printf("caddy 验证命令: %s\n", CADDY_VALIDATE)
	fmt.Printf("caddy 停止命令: %s\n", CADDY_STOP)
	fmt.Printf("caddy 重启命令: %s\n", CADDY_RESTART)
	fmt.Printf("caddy 启动命令: %s\n", CADDY_START)
	cmd := exec.Command("sh", "-c", CADDY_CMD_VERSION)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		fmt.Printf("执行命令失败: %v\n", err)
		os.Exit(1)
	}
	http.HandleFunc("/api/caddyfile", handleCaddyfile)

	// 静态文件服务
	fs := http.FileServer(http.Dir(frontPath))
	http.Handle("/", fs)

	// API路由
	http.HandleFunc("/api/caddy/start", handleCaddyStart)
	http.HandleFunc("/api/caddy/stop", handleCaddyStop)
	http.HandleFunc("/api/caddy/reload", handleCaddyReload)
	http.HandleFunc("/api/logs", handleLogs)
	http.HandleFunc("/api/caddyfile/edit", handleEditCaddyfile)

	log.Println("Server starting on : http://localhost:" + serverPort)
	if err := http.ListenAndServe(":"+serverPort, nil); err != nil {
		log.Fatal(err)
	}
}

// 新增：读取 Caddyfile 的接口
func handleCaddyfile(w http.ResponseWriter, r *http.Request) {
	// 添加日志
	log.Println("Handling request to fetch Caddyfile")

	content, err := os.ReadFile(caddyfilePath)
	if err != nil {
		log.Printf("Failed to read Caddyfile: %v", err) // 添加日志
		http.Error(w, "无法读取 Caddyfile: "+err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Write(content)
}

// 编辑Caddyfile的接口
func handleEditCaddyfile(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	content, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "无法读取请求体: "+err.Error(), http.StatusBadRequest)
		return
	}

	err = os.WriteFile(caddyfilePath, content, 0644)
	if err != nil {
		http.Error(w, "无法写入Caddyfile: "+err.Error(), http.StatusInternalServerError)
		return
	}

	json.NewEncoder(w).Encode(Response{Success: true, Message: "Caddyfile已更新"})
}

// 启动Caddy服务
func handleCaddyStart(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}


	// 打开日志文件（以追加模式）
	errLogFile, err := os.OpenFile(CADDY_ERROR_LOG_PATH, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		json.NewEncoder(w).Encode(Response{Success: false, Message: "无法打开日志文件: " + err.Error()})
		return
	}
	defer errLogFile.Close()
	if ENV == "docker" {
		caddyCmd = exec.Command("sh", "-c", CADDY_START)
	} else {
		caddyCmd = exec.Command("caddy", "start", "--config", CADDYFILE_PATH)
	}
	caddyCmd.Stderr = errLogFile
	if err := caddyCmd.Start(); err != nil {
		json.NewEncoder(w).Encode(Response{Success: false, Message: "启动Caddy失败: " + err.Error()})
		return
	}

	json.NewEncoder(w).Encode(Response{Success: true, Message: "Caddy服务已启动"})
}

// 停止Caddy服务
func handleCaddyStop(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

		// 打开日志文件（以追加模式）
		errLogFile, err := os.OpenFile(CADDY_ERROR_LOG_PATH, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			json.NewEncoder(w).Encode(Response{Success: false, Message: "无法打开日志文件: " + err.Error()})
			return
		}
		defer errLogFile.Close()
		// 如果caddyCmd为nil，尝试执行全局caddy stop，因为Caddy可能在外部启动
		var stopCmd *exec.Cmd
		if ENV == "docker" {
			stopCmd = exec.Command("sh", "-c", CADDY_STOP)
		} else {
			stopCmd = exec.Command("caddy", "stop")
		}
		stopCmd.Stderr = errLogFile
		if err := stopCmd.Run(); err != nil {
			// 即使外部Caddy停止失败，也可能没有正在运行的Caddy实例，或者权限问题
			// 对于用户来说，如果服务确实停了，或者本来就没启动，这个消息可能是可接受的
			// 但为了更准确，可以考虑检查Caddy的实际运行状态
			log.Printf("Attempted to stop an externally managed Caddy, or Caddy was not running. Error (if any): %v", err)
			// 考虑到Caddy可能并未通过本程序启动，此时返回成功可能更符合用户预期
			// 或者，可以返回一个更中性的消息，例如“尝试停止Caddy服务”
			json.NewEncoder(w).Encode(Response{Success: true, Message: "尝试停止Caddy服务。如果Caddy由外部管理，请检查其状态。"})
			return
		}
		json.NewEncoder(w).Encode(Response{Success: true, Message: "Caddy服务已停止 (可能是外部管理的实例)"})
		return
}

// 重载Caddy配置
func handleCaddyReload(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// 打开日志文件（以追加模式）
	errLogFile, err := os.OpenFile(CADDY_ERROR_LOG_PATH, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		json.NewEncoder(w).Encode(Response{Success: false, Message: "无法打开日志文件: " + err.Error()})
		return
	}
	defer errLogFile.Close()

	var cmd *exec.Cmd
	if ENV == "docker" {
		cmd = exec.Command("sh", "-c", CADDY_RESTART)
	} else {
		cmd = exec.Command("caddy", "reload", "--config", CADDYFILE_PATH)
	}
	cmd.Stderr = errLogFile
	if err := cmd.Run(); err != nil {
		json.NewEncoder(w).Encode(Response{Success: false, Message: "重载配置失败: " + err.Error()})
		return
	}

	json.NewEncoder(w).Encode(Response{Success: true, Message: "配置已重载"})
}

// WebSocket处理日志流
func handleLogs(w http.ResponseWriter, r *http.Request) {
	// 	conn, err := upgrader.Upgrade(w, r, nil) // 升级HTTP连接为WebSocket连接
	// if err != nil {

	// }
}
